/*
-----------------------------------------------------------------------------
Filename:    SandBox.cpp
-----------------------------------------------------------------------------
*/

#include "SandBox.h"

using namespace Ogre;
using namespace OgreBites;


#define MaxStrength 1e7f
//-------------------------------------------------------------------------------------
SandBox::SandBox(void)
{
    mBrushSizeTerrainSpace = 0.03;
	mTerrainPos = Ogre::Vector3(0, 0, 0);
	PhysXDebug = false;
	bTerrainLoaded = false;
	bSceneSetUp = false;
	nCameraSpeed = 100;
	
	extern logwriter logFile;
	logFile.writeEntry("log_start");

	extern AppSettings settings;
	bBenchmarking = settings.applicationSettings.bLogBenchmark;

	mPhysXWorld = new PhysXWorld();
	mMeshManager = NxOgre::MeshManager::getSingleton();
}
//-------------------------------------------------------------------------------------
SandBox::~SandBox(void)
{
	if(bSceneSetUp)
	{
		delete mMap;
	}

	extern logwriter logFile;
	logFile.close();
	extern AppSettings settings;
	settings.saveSettings();
}

//-------------------------------------------------------------------------------------
void SandBox::createScene(void)
{
	if(!bBenchmarking)
	{
		mSceneImporter.importSceneDBFromXml("SaveFiles/SaveDB.xml");
		mSceneExporter.init("SaveFiles/SaveDB.xml");
		mGui->mMainMenu->show();

		Ogre::StringVector saveNames;
		int count = mSceneImporter.saveFiles.size();
		for(int i=0;i<count;i++)
		{
			saveNames.push_back(mSceneImporter.saveFiles.at(i)->getName());
		}

		mGui->mMainMenu->injectMenuItems(saveNames);
		mGui->setGuimode(true);
	}
	else
	{
		setupBenchmark();
	}
}

//-------------------------------------------------------------------------------------

void SandBox::buildWorld(Ogre::String saveFileName)
{

	extern AppSettings settings;

	if(settings.applicationSettings.bUseShadows)
	{
		// set shadow properties
		mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_MODULATIVE);
		mSceneMgr->setShadowColour(ColourValue(0.5, 0.5, 0.5));
		mSceneMgr->setShadowTextureSize(1024);
		mSceneMgr->setShadowTextureCount(1);
	}

  
	mCamera->setPosition(Ogre::Vector3(-45.1056, 22.243, -49.2175));
	mCamera->setOrientation(Ogre::Quaternion(-0.720312,0.123759, 0.672868, 0.115734));
	mCamera->setNearClipDistance(0.5);
	mCamera->setFarClipDistance(50000);
	mCameraMan->setTopSpeed(nCameraSpeed);

	mGui->setGuimode(false);

	if (mRoot->getRenderSystem()->getCapabilities()->hasCapability(Ogre::RSC_INFINITE_FAR_PLANE))
    {
        mCamera->setFarClipDistance(0);   // enable infinite far clip distance if we can
    }

	mMap = new Map(mSceneMgr,"terrain_empty.png");
	mWeatherSystem = new WeatherSystem(mSceneMgr, mMap);

	mSceneImporter.importSaveDataFromXmlFile(saveFileName);
	mSceneImporter.importScene(mPredefinedCameraDescriptions,mSceneMgr,mMap,mWeatherSystem);

	mEditEntity = mSceneMgr->createEntity("editMarker", "Sphere01.mesh");
	mEditEntity->setCastShadows(false);
	mEditNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
	mEditNode->attachObject(mEditEntity);
	mEditNode->setScale(0.05, 0.05, 0.05);

	bSceneSetUp = true;
    setupPhysics();
	
	mSceneImporter.importActors(mRenderSystem,mSceneMgr,mScene,mPhysXWorld);

	printf("\n%s","--------------------------------------------------");
	printf("\n%s","Scene loaded...");
	printf("\n%s","--------------------------------------------------");
}

//-------------------------------------------------------------------------------------

void SandBox::setupPhysics(void)
{
	extern AppSettings settings;

	if(bSceneSetUp)
	{
		  // Create the world.
	  mWorld = NxOgre::World::createWorld();
  
	  NxOgre::ResourceSystem::getSingleton()->openProtocol(new Critter::OgreResourceProtocol());

	  mWorld->getRemoteDebugger()->connect();

	  // Create the scene
	  NxOgre::SceneDescription scene_description;
	  scene_description.mGravity = NxOgre::Constants::MEAN_EARTH_GRAVITY;
	  if(settings.applicationSettings.bUseHardwarePhysX)
	  {
			 scene_description.mUseHardware = true;
	  }
	  else
	  {
		     scene_description.mUseHardware = false;
	  }
	  scene_description.mWorkerThreadsCount = 2;
	  scene_description.mBackgroundThreadsCount = 2;
	  scene_description.mFlags |= NxOgre::SceneFlags::EnableMultithread | NxOgre::SceneFlags::FluidPerformanceHint | NxOgre::SceneFlags::AlternativeFluidTriangleCollision;


	  mScene = mWorld->createScene(scene_description);
  
	  // Set default material properties
	  mDefaultMaterial = mScene->getMaterial(0);
	  mDefaultMaterial->setRestitution(0.1f);
	  mDefaultMaterial->setDynamicFriction(0.9);
	  mDefaultMaterial->setStaticFriction(0.5);
  
	  // Plane creation
	  mScene->createSceneGeometry(NxOgre::PlaneGeometryDescription());

	  // Create the rendersystem.
	  mRenderSystem = new Critter::RenderSystem(mScene, mSceneMgr);

		NxOgre::SceneGeometry * sg;

		Ogre::TerrainGroup::TerrainIterator ti = mMap->getTerrainGroup()->getTerrainIterator();
		while (ti.hasMoreElements())
		{
			Terrain * t = ti.getNext()->instance;
			sg = mRenderSystem->createTerrain(t);
		}
  

		printf("\n%s","--------------------------------------------------");
		printf("\n%s","Physical world set up...");
		printf("\n%s","--------------------------------------------------");
	}
}

//-------------------------------------------------------------------------------------

void SandBox::resetPhysics(void)
{
	if(bSceneSetUp)
	{
		mPhysXWorld->clearAll();
		delete mRenderSystem;
		NxOgre::World::destroyWorld();
		setupPhysics();
	}
}

//-------------------------------------------------------------------------------------

void SandBox::advancePhysX(const Ogre::FrameEvent& evt)
{
	if(bSceneSetUp)
	{
	  mWorld->advance(evt.timeSinceLastFrame);
	  mLastTimeStep = mScene->getTimeStep().getModified();
	}
}

//-------------------------------------------------------------------------------------

void SandBox::editMap(const Ogre::FrameEvent& evt)
{
	if(bSceneSetUp&&(!bBenchmarking))
	{
		bool terrainModified = false;
		// fire ray
		Ogre::Ray ray; 
		ray = mCamera->getCameraToViewportRay(0.5, 0.5);
		//ray = mTrayMgr->getCursorRay(mCamera);

		Ogre::TerrainGroup::RayResult rayResult = mMap->getTerrainGroup()->rayIntersects(ray);
		if (rayResult.hit)
		{
			
			mEditEntity->setVisible(true);
			mEditNode->setPosition(rayResult.position);

			Ogre::Real brushSizeWorldSpace = 250 * mBrushSizeTerrainSpace;
			Ogre::Sphere sphere(rayResult.position, brushSizeWorldSpace);
			
			if(mGui->mEditWindow->getActivitySelection() == EditWindow::Activity_EditTerrain)
			{
		

					if (mKeyboard->isKeyDown(OIS::KC_EQUALS) || mKeyboard->isKeyDown(OIS::KC_ADD) ||
					mKeyboard->isKeyDown(OIS::KC_MINUS) || mKeyboard->isKeyDown(OIS::KC_SUBTRACT))
					{
						bool raise = false;

						if (mKeyboard->isKeyDown(OIS::KC_EQUALS) || mKeyboard->isKeyDown(OIS::KC_ADD))
						{
							raise = true;
						}
						else
						{
							raise = false;
						}

						terrainModified = mMap->editTerrain(rayResult.position, evt.timeSinceLastFrame, mBrushSizeTerrainSpace, raise);
					}

			}
		}
		else
		{
			mEditEntity->setVisible(false);
		}

		if(terrainModified)
		{
			mMap->getTerrainGroup()->update();
		}
	}
}

//-------------------------------------------------------------------------------------
void SandBox:: correctPosition(void)
{
	if(bSceneSetUp)
	{
	//don't let the camera go under the terrain

			Vector3 camPos = mCamera->getPosition();
			Ray ray;
			ray.setOrigin(Vector3(camPos.x, mTerrainPos.y + 10000, camPos.z));
			ray.setDirection(Vector3::NEGATIVE_UNIT_Y);

			TerrainGroup::RayResult rayResult = mMap->getTerrainGroup()->rayIntersects(ray);
			Real distanceAboveTerrain = 1;
			Real fallSpeed = 300;
			Real newy = camPos.y;
			if (rayResult.hit)
			{
				if (camPos.y < rayResult.position.y + distanceAboveTerrain)
				{
					newy = std::max(rayResult.position.y + distanceAboveTerrain, newy);
					mCamera->setPosition(camPos.x, newy, camPos.z);
				}
				
			}
	}
}

//-------------------------------------------------------------------------------------

void SandBox::setupBenchmark(void)
{
	this->nBenchmarkStartTime = this->getCurrentTimeScale1();

	mGui->mMainMenu->hide();

	buildWorld("SaveFiles/benchmark.xml");
	
	mGui->mEditWindow->hide();
	mGui->mStartMenu->hide();
	mGui->mTestWindow->hide();
	mGui->mWaterWindow->hide();
	mGui->mWeatherWindow->hide();
	mEditNode->setVisible(false);
	
	mCamera->setPosition(this->mPredefinedCameraDescriptions->lCameraDescriptions.at(0)->getPosition());
	mCamera->setOrientation(this->mPredefinedCameraDescriptions->lCameraDescriptions.at(0)->getOrientation());

	mPhysXWorld->fireAllEmitters();

	this->resetBenchMarkData();
}

//-------------------------------------------------------------------------------------

void SandBox::advanceBenchmark(void)
{
	DWORD currentTimeStep = this->getCurrentTimeScale1();
	
	if((currentTimeStep > (nBenchmarkStartTime+30))&&(mShutDown==false))
	{
		this->writeBenchMarkResults("benchmark.xml");
		mShutDown = true;
	}
}

//-------------------------------------------------------------------------------------

bool SandBox::frameRenderingQueued(const Ogre::FrameEvent& evt)
{
	bool ret = BaseEngine::frameRenderingQueued(evt);

	if(bSceneSetUp)
	{

	  editMap(evt);
	  advancePhysX(evt);
	  correctPosition();

	  if(bBenchmarking)
	  {
		  advanceBenchmark();
	  }

	  if(!bTerrainLoaded)
	  {
		  if (mMap->getTerrainGroup()->isDerivedDataUpdateInProgress())
		  {
			  mTrayMgr->moveWidgetToTray(mDetailsPanel, OgreBites::TL_NONE, 0);
			  mDetailsPanel->hide();

			  mGui->showLoadingLabel("Updating scene, please wait...");
		  }
		  else
		  {
			  mGui->hideLoadingLabel();

			  if(bBenchmarking)
			  {
				  	mGui->mEditWindow->hide();
					mGui->mStartMenu->hide();
					mGui->mTestWindow->hide();
					mGui->mWaterWindow->hide();
					mGui->mWeatherWindow->hide();
			  }

			  mTrayMgr->moveWidgetToTray(mDetailsPanel, OgreBites::TL_TOPRIGHT, 0);
			  mDetailsPanel->show();
			  bTerrainLoaded = true;
		  }
	  }

	}
    return ret;
}
//-------------------------------------------------------------------------------------
bool  SandBox::keyPressed( const OIS::KeyEvent &arg )
{
	if(bSceneSetUp)
	{
		if(bTerrainLoaded&&(!bBenchmarking))
		{
				BaseEngine::keyPressed(arg);
			
				if(arg.key == OIS::KC_F9)
				{
					float mapX = mTerrainPos.x;
					float mapY = mTerrainPos.y;
					float mapZ = mTerrainPos.z;

					float camX = mCamera->getPosition().x;
					float camY = mCamera->getPosition().y;
					float camZ = mCamera->getPosition().z;

					float camoW =  mCamera->getOrientation().w;
					float camoX =  mCamera->getOrientation().x;
					float camoY =  mCamera->getOrientation().y;
					float camoZ =  mCamera->getOrientation().z;
				
					extern logwriter logFile;
					logFile.writeEntry("Map position:", mapX , mapY, mapZ);
					logFile.writeEntry("Camera position:", camX , camY, camZ);
					logFile.writeEntry("Camera orientation:", camoW, camoX , camoY, camoZ);
				
				}
				else if(arg.key == OIS::KC_5)
				{
					CameraDescription *temp = new CameraDescription("na",mCamera->getPosition(), mCamera->getOrientation());
					mPredefinedCameraDescriptions->lCameraDescriptions.push_back(temp);
				}
				else if(arg.key == OIS::KC_6)
				{
					
				}
				else if(arg.key == OIS::KC_V)
				{
				   if(!PhysXDebug)
				   {
					   mRenderSystem->setVisualisationMode(NxOgre::Enums::VisualDebugger_ShowAll);
					   PhysXDebug = true;
				   }
				   else
				   {
					   mRenderSystem->setVisualisationMode(NxOgre::Enums::VisualDebugger_ShowNone);
					   PhysXDebug = false;
				   }
	   
				}
				else if (arg.key == OIS::KC_H)
				{
				}
				else if (arg.key == OIS::KC_F12)
				{
				}
				else if (arg.key == OIS::KC_F10)
				{
				}
				else if (arg.key == OIS::KC_F11)
				{
				}
				else if(arg.key == OIS::KC_END)
				{
					mMap->initBlendMaps();
				}
				else if(mGui->mEditWindow->getActivitySelection() == EditWindow::Activity_Edit)
				{

						if (arg.key == OIS::KC_I)
						{
							int selection = mGui->mEditWindow->getActorSelection();
							mPhysXWorld->moveSceneryObject(selection,WorldEnums::Angle_X,0.1);
						}
						else if (arg.key == OIS::KC_K)
						{
							int selection = mGui->mEditWindow->getActorSelection();
							mPhysXWorld->moveSceneryObject(selection,WorldEnums::Angle_X,-0.1);
						}
						else if (arg.key == OIS::KC_J)
						{
							int selection = mGui->mEditWindow->getActorSelection();
							mPhysXWorld->moveSceneryObject(selection,WorldEnums::Angle_Z,0.1);
						}
						else if (arg.key == OIS::KC_L)
						{
							int selection = mGui->mEditWindow->getActorSelection();
							mPhysXWorld->moveSceneryObject(selection,WorldEnums::Angle_Z,-0.1);
						}
						else if (arg.key == OIS::KC_U)
						{
							int selection = mGui->mEditWindow->getActorSelection();
							mPhysXWorld->moveSceneryObject(selection,WorldEnums::Angle_Y,0.1);
						}
						else if (arg.key == OIS::KC_O)
						{
							int selection = mGui->mEditWindow->getActorSelection();
							mPhysXWorld->moveSceneryObject(selection,WorldEnums::Angle_Y,-0.1);
						}
						else if (arg.key == OIS::KC_NUMPAD2)
						{
							int selection = mGui->mEditWindow->getActorSelection();
							mPhysXWorld->scaleSceneryObject(selection,-0.01);
						}
						else if (arg.key == OIS::KC_NUMPAD8)
						{
							int selection = mGui->mEditWindow->getActorSelection();
							mPhysXWorld->scaleSceneryObject(selection,0.01);
						}
						else if (arg.key == OIS::KC_NUMPAD4)
						{
							int selection = mGui->mEditWindow->getActorSelection();
							mPhysXWorld->rotateSceneryObject(selection,45);
						}
						else if (arg.key == OIS::KC_NUMPAD6)
						{
							int selection = mGui->mEditWindow->getActorSelection();
							mPhysXWorld->rotateSceneryObject(selection,-45);
						}
						else if (arg.key == OIS::KC_DELETE)
						{
							/*
							int selection = mGui->mEditWindow->getActorSelection();
							mPhysXWorld->deleteSceneryObject(selection);
							mGui->mEditWindow->injectActorNames(mPhysXWorld->returnActorNames());
							mGui->mEditWindow->injectHolderActorNames(mPhysXWorld->returnHolderActorNames());
							int holderSelection = mGui->mEditWindow->getHolderActorSelection();
							mGui->mEditWindow->injectEmitterNames(mPhysXWorld->returnEmitterNames(holderSelection));
							mGui->mEditWindow->refresh();
							*/
						}
				}
  
		}
	}
	return true;
}
//-------------------------------------------------------------------------------------
bool SandBox::mousePressed( const OIS::MouseEvent &arg, OIS::MouseButtonID id )
{
	
	bool ret = BaseEngine::mousePressed(arg,id);

	if(bSceneSetUp)
	{
			int nRightMouse = 1;
			int nMiddleMouse = 2;

			if(id == nMiddleMouse)
			{
				mGui->toggleGuimode();
			}
			else if(id == nRightMouse)
			{
		
				EditWindow::eObjectSelection objectSelection = mGui->mEditWindow->getObjectSelection();

						if(objectSelection == EditWindow::Object_WaterEmitter)
						{
							int holderSelection = mGui->mEditWindow->getHolderActorSelection();
							Lake *holder = mPhysXWorld->getHolderActor(holderSelection);
							if(holder != 0)
							{
								Ogre::Vector3 cursorPos = mEditNode->getPosition();
								mPhysXWorld->attachWaterEmitter(holder,mRenderSystem, mSceneMgr, cursorPos.x, cursorPos.y, cursorPos.z);
							}
					
						}
						else if(objectSelection == EditWindow::Object_BoxGroup)
						{
							if(mEditEntity->isVisible())
							{
								Ogre::Vector3 cursorPos = mEditNode->getPosition();

								Critter::BodyDescription bodyDescription;
								bodyDescription.mMass = 40.0f; // Set the mass to 40kg.

								mRenderSystem->createBody(NxOgre::BoxDescription(1,1,1), NxOgre::Vec3(cursorPos.x,cursorPos.y+5,cursorPos.z), "cube.1m.mesh", bodyDescription);
								mRenderSystem->createBody(NxOgre::BoxDescription(1,1,1), NxOgre::Vec3(cursorPos.x + 0.5,cursorPos.y + 7,cursorPos.z + 0.3), "cube.1m.mesh", bodyDescription);
								mRenderSystem->createBody(NxOgre::BoxDescription(1,1,1), NxOgre::Vec3(cursorPos.x + 0.3,cursorPos.y + 10,cursorPos.z + 0.1), "cube.1m.mesh", bodyDescription);
								mRenderSystem->createBody(NxOgre::BoxDescription(1,1,1), NxOgre::Vec3(cursorPos.x + 0.9,cursorPos.y + 6,cursorPos.z + 0.8), "cube.1m.mesh", bodyDescription);
								mRenderSystem->createBody(NxOgre::BoxDescription(1,1,1), NxOgre::Vec3(cursorPos.x + 0.7,cursorPos.y + 2,cursorPos.z + 0.7), "cube.1m.mesh", bodyDescription);
								mRenderSystem->createBody(NxOgre::BoxDescription(1,1,1), NxOgre::Vec3(cursorPos.x + 1,cursorPos.y + 12,cursorPos.z + 0), "cube.1m.mesh", bodyDescription);
								mRenderSystem->createBody(NxOgre::BoxDescription(1,1,1), NxOgre::Vec3(cursorPos.x + 0.1,cursorPos.y + 7.5,cursorPos.z + 0.4), "cube.1m.mesh", bodyDescription);
								mRenderSystem->createBody(NxOgre::BoxDescription(1,1,1), NxOgre::Vec3(cursorPos.x + 2,cursorPos.y + 6,cursorPos.z + 0.8), "cube.1m.mesh", bodyDescription);

							}
						}
						else if(objectSelection == EditWindow::Object_Block1)
						{
								std::cout << "\nSelected building: Block 1";
								mPhysXWorld->createScenery(WorldEnums::Scenery_Block1,  NxOgre::Vec3(mEditNode->getPosition().x,mEditNode->getPosition().y,mEditNode->getPosition().z), mScene, mSceneMgr);
						}
						else if(objectSelection == EditWindow::Object_Block2)
						{
								std::cout << "\nSelected building: Block 2";
								mPhysXWorld->createScenery(WorldEnums::Scenery_Block2,  NxOgre::Vec3(mEditNode->getPosition().x,mEditNode->getPosition().y,mEditNode->getPosition().z), mScene, mSceneMgr);
						
						}
						else if(objectSelection == EditWindow::Object_Block3)
						{
								std::cout << "\nSelected building: Block 3";
								mPhysXWorld->createScenery(WorldEnums::Scenery_Block3,  NxOgre::Vec3(mEditNode->getPosition().x,mEditNode->getPosition().y,mEditNode->getPosition().z), mScene, mSceneMgr);
						
						}
						else if(objectSelection == EditWindow::Object_House1)
						{
								std::cout << "\nSelected building: House 1";
								mPhysXWorld->createScenery(WorldEnums::Scenery_House1,  NxOgre::Vec3(mEditNode->getPosition().x,mEditNode->getPosition().y,mEditNode->getPosition().z), mScene, mSceneMgr);
						}
						else if(objectSelection == EditWindow::Object_House2)
						{
								std::cout << "\nSelected building: House 2";
								mPhysXWorld->createScenery(WorldEnums::Scenery_House2,  NxOgre::Vec3(mEditNode->getPosition().x,mEditNode->getPosition().y,mEditNode->getPosition().z), mScene, mSceneMgr);
						
						}
						else if(objectSelection == EditWindow::Object_Tree1)
						{
								std::cout << "\nSelected foilage: Tree 1";
								mPhysXWorld->createScenery(WorldEnums::Scenery_Tree1,  NxOgre::Vec3(mEditNode->getPosition().x,mEditNode->getPosition().y,mEditNode->getPosition().z), mScene, mSceneMgr);
						}
						else if(objectSelection == EditWindow::Object_Tree2)
						{
								std::cout << "\nSelected foilage: Tree 2";
								mPhysXWorld->createScenery(WorldEnums::Scenery_Tree2,  NxOgre::Vec3(mEditNode->getPosition().x,mEditNode->getPosition().y,mEditNode->getPosition().z), mScene, mSceneMgr);
						
						}
						else if(objectSelection == EditWindow::Object_Lake1)
						{
								std::cout << "\nSelected building: Lake 1";
								mPhysXWorld->createScenery(WorldEnums::Scenery_Lake1,  NxOgre::Vec3(mEditNode->getPosition().x,mEditNode->getPosition().y,mEditNode->getPosition().z), mScene, mSceneMgr);
						
						}
						else if(objectSelection == EditWindow::Object_Lake2)
						{
								std::cout << "\nSelected building: Lake 2";
								mPhysXWorld->createScenery(WorldEnums::Scenery_Lake2,  NxOgre::Vec3(mEditNode->getPosition().x,mEditNode->getPosition().y,mEditNode->getPosition().z), mScene, mSceneMgr);
						
						}
						else if(objectSelection == EditWindow::Object_Lake3)
						{
								std::cout << "\nSelected building: Lake 3";
								mPhysXWorld->createScenery(WorldEnums::Scenery_Lake3,  NxOgre::Vec3(mEditNode->getPosition().x,mEditNode->getPosition().y,mEditNode->getPosition().z), mScene, mSceneMgr);
						
						}
					
						//refresh GUI
						mGui->mEditWindow->injectActorNames(mPhysXWorld->returnActorNames());
						mGui->mEditWindow->injectHolderActorNames(mPhysXWorld->returnHolderActorNames());
						int holderSelection = mGui->mEditWindow->getHolderActorSelection();
						mGui->mEditWindow->injectEmitterNames(mPhysXWorld->returnEmitterNames(holderSelection));
						mGui->mEditWindow->refresh();
				}	
	}
	else
	{
		//we are in the main menu
	}

	return ret;
}
//-------------------------------------------------------------------------------------
bool SandBox::mouseMoved( const OIS::MouseEvent &arg )
{
	bool ret = false;

	if(bSceneSetUp)
	{
		if(bTerrainLoaded&&(!bBenchmarking))
		{
			ret = BaseEngine::mouseMoved(arg);
		}
	}
	else
	{
		//we are in the main menu
		ret = BaseEngine::mouseMoved(arg);
	}

	return ret;
}
//-------------------------------------------------------------------------------------
void SandBox::itemSelected(SelectMenu* menu)
{
	if(bSceneSetUp)
	{
			extern AppSettings settings;

			if(menu->getName() == "TWaterWindowMenu")
			{
				Ogre::String text = "Value: ";
				Ogre::String value = "";
		
				WaterWindow::eWaterParams selection = mGui->mWaterWindow->getSelection();

				switch(selection)
				{
				case WaterWindow::Param_MaxParticles:
					value = Ogre::StringConverter::toString(settings.waterSettings.mMaxParticles);
					break;
				case WaterWindow::Param_KernelRadiusMultiplier:
					value = Ogre::StringConverter::toString(settings.waterSettings.mKernelRadiusMultiplier);
					break;
				case WaterWindow::Param_RestParticlesPerMetre:
					value = Ogre::StringConverter::toString(settings.waterSettings.mRestParticlesPerMetre);
					break;
				case WaterWindow::Param_PacketSizeMultiplier:
					value = Ogre::StringConverter::toString(settings.waterSettings.mPacketSizeMultiplier);
					break;
				case WaterWindow::Param_MotionLimitMultiplier:
					value = Ogre::StringConverter::toString(settings.waterSettings.mMotionLimitMultiplier);
					break;
				case WaterWindow::Param_CollisionDistanceMultiplier:
					value = Ogre::StringConverter::toString(settings.waterSettings.mCollisionDistanceMultiplier);
					break;
				case WaterWindow::Param_Stiffness:
					value = Ogre::StringConverter::toString(settings.waterSettings.mStiffness);
					break;
				case WaterWindow::Param_Viscosity:
					value = Ogre::StringConverter::toString(settings.waterSettings.mViscosity);
					break;
				case WaterWindow::Param_RestDensity:
					value = Ogre::StringConverter::toString(settings.waterSettings.mRestDensity);
					break;
				case WaterWindow::Param_StartHeight:
					value = Ogre::StringConverter::toString(settings.waterSettings.mStartHeight);
					break;
				case WaterWindow::Param_ParticleLifetime:
					value = Ogre::StringConverter::toString(settings.waterSettings.mParticleLifetime);
					break;
				case WaterWindow::Param_Rate:
					value = Ogre::StringConverter::toString(settings.waterSettings.mRate);
					break;
				case WaterWindow::Param_FluidSpeed:
					value = Ogre::StringConverter::toString(settings.waterSettings.mFluidSpeed);
					break;
				case WaterWindow::Param_ReplusionCoefficient:
					value = Ogre::StringConverter::toString(settings.waterSettings.mReplusionCoefficient);
					break;
				case WaterWindow::Param_DimensionX:
					value = Ogre::StringConverter::toString(settings.waterSettings.mDimensionX);
					break;
				case WaterWindow::Param_DimensionY:
					value = Ogre::StringConverter::toString(settings.waterSettings.mDimensionY);
					break;
				case WaterWindow::Param_ParticleSize:
					value = Ogre::StringConverter::toString(settings.waterSettings.mParticleSize);
					break;
				}

				text.append(value);
				mGui->mWaterWindow->mParamValueLabel->setCaption(text);
			}
			else if(menu->getName() == "TDayTimeMenu")
			{
				WeatherWindow::eDayTimeSelection selection = mGui->mWeatherWindow->getDayTimeSelection();

				switch(selection)
				{
				case WeatherSystem::DayTime_Dawn:
					mWeatherSystem->setDayTime(WeatherSystem::DayTime_Dawn);
					break;
				case WeatherSystem::DayTime_Noon:
					mWeatherSystem->setDayTime(WeatherSystem::DayTime_Noon);
					break;
				case WeatherSystem::DayTime_AfterNoon:
					mWeatherSystem->setDayTime(WeatherSystem::DayTime_AfterNoon);
					break;
				case WeatherSystem::DayTime_SunSet:
					mWeatherSystem->setDayTime(WeatherSystem::DayTime_SunSet);
					break;
				case WeatherSystem::DayTime_Night:
					mWeatherSystem->setDayTime(WeatherSystem::DayTime_Night);
					break;
				}

				bTerrainLoaded = false;
			}
			else if(menu->getName() == "TWeatherFenomenMenu")
			{
				WeatherWindow::eWeatherFenomenSelection selection = mGui->mWeatherWindow->getWeatherFenomenSelection();

				switch(selection)
				{
				case WeatherWindow::Fenomen_Clear:
					mWeatherSystem->stopRain();
					mWeatherSystem->stopSnow();
					break;
				case WeatherWindow::Fenomen_Rain:
					mWeatherSystem->stopSnow();
					mWeatherSystem->createRain();
					break;
				case WeatherWindow::Fenomen_Snow:
					mWeatherSystem->stopRain();
					mWeatherSystem->createSnow();
					break;
				}
			}
			else if(menu->getName() == "TActivityMenu")
			{
				int actorSelection;
				int holderSelection;
				mGui->mEditWindow->refresh();

				EditWindow::eActivityType selection = mGui->mEditWindow->getActivitySelection();

				switch(selection)
				{
				case EditWindow::Activity_Edit:
			
					actorSelection = mGui->mEditWindow->getActorSelection();
					mGui->mEditWindow->injectActorNames(mPhysXWorld->returnActorNames());
					mGui->mEditWindow->injectHolderActorNames(mPhysXWorld->returnHolderActorNames());
					mGui->mEditWindow->injectEmitterNames(mPhysXWorld->returnEmitterNames(actorSelection));

							std::cout << "\nselection: " << actorSelection;
							if(mPhysXWorld->isHolderActor(actorSelection))
							{
								std::cout << " is holder!";
								mGui->mEditWindow->showEmitterWindow(true);
							}
							else
							{
								std::cout << " not a  holder!";
								mGui->mEditWindow->showEmitterWindow(false);
							}
							mGui->mEditWindow->refresh();

					break;

				case EditWindow::Activity_Create:
					mGui->mEditWindow->injectHolderActorNames(mPhysXWorld->returnHolderActorNames());
					break;

				case EditWindow::Activity_EditTerrain:
					
					break;
				}
			}
			else if(menu->getName() == "TStartMenu")
			{
				StartMenu::eStartMenuSelection selection = mGui->mStartMenu->getSelection();

				switch(selection)
				{
				case StartMenu::Selection_SetWaterParams :

					mGui->mWaterWindow->show();
					mGui->mWeatherWindow->hide();
					mGui->mEditWindow->hide();
					mGui->mTestWindow->hide();

					break;

				case StartMenu::Selection_SetWeather:

					mGui->mWaterWindow->hide();
					mGui->mWeatherWindow->show();
					mGui->mEditWindow->hide();
					mGui->mTestWindow->hide();

					break;

				case StartMenu::Selection_EditScene:

					mGui->mWaterWindow->hide();
					mGui->mWeatherWindow->hide();
					mGui->mEditWindow->show();
					mGui->mTestWindow->hide();

					break;

				case StartMenu::Selection_TestEvents:

					mGui->mWaterWindow->hide();
					mGui->mWeatherWindow->hide();
					mGui->mEditWindow->hide();
					mGui->mTestWindow->show();

					break;
				}
		
			}
			else if(menu->getName() == "TObjectMenu")
			{
				mGui->mEditWindow->refresh();
			}
			else if(menu->getName() == "TActorMenu")
			{
				int selection = mGui->mEditWindow->getActorSelection();
				std::cout << "\nselection: " << selection;
				if(mPhysXWorld->isHolderActor(selection))
				{
					std::cout << " is holder!";

					mGui->mEditWindow->injectEmitterNames(mPhysXWorld->returnEmitterNames(selection));

					mGui->mEditWindow->showEmitterWindow(true);
				}
				else
				{
					std::cout << " not a  holder!";
					mGui->mEditWindow->showEmitterWindow(false);
				}
				mGui->mEditWindow->refresh();
			}
	}
	else
	{
	   //We are in the main menu

		if(menu->getName() == "TMainMenu")
		{
			int selection = menu->getSelectionIndex();
			mGui->mMainMenu->setDescriptionText(mSceneImporter.saveFiles.at(selection)->getDescription());
		}

		}
}
//-------------------------------------------------------------------------------------
void SandBox::buttonHit(Button* button)
{
	if(bSceneSetUp)
	{

			if(  (button->getName() == "TUpButton") ||  (button->getName() == "TDownButton") )
			{
				extern AppSettings settings;	

				Ogre::String text = "Value: ";
				Ogre::String value = "";

				WaterWindow::eWaterParams selection = mGui->mWaterWindow->getSelection();

				switch(selection)
				{
				case WaterWindow::Param_MaxParticles:
					if(button->getName() == "TUpButton")
					{
						settings.waterSettings.mMaxParticles += 100;
					}
					else
					{
						if(int(settings.waterSettings.mMaxParticles) - 100 > 0)
						{
							settings.waterSettings.mMaxParticles -= 100;
						}
						else
						{
							settings.waterSettings.mMaxParticles = 0;
						}
					}
					value = Ogre::StringConverter::toString(settings.waterSettings.mMaxParticles);
					break;
				case WaterWindow::Param_KernelRadiusMultiplier:
					if(button->getName() == "TUpButton")
					{
						settings.waterSettings.mKernelRadiusMultiplier += 0.1;
					}
					else
					{
						if(settings.waterSettings.mKernelRadiusMultiplier - 0.1 >0)
						{
							settings.waterSettings.mKernelRadiusMultiplier -= 0.1;
						}
						else
						{
							settings.waterSettings.mKernelRadiusMultiplier = 0;
						}
					}
					value = Ogre::StringConverter::toString(settings.waterSettings.mKernelRadiusMultiplier);
					break;
				case WaterWindow::Param_RestParticlesPerMetre:
					if(button->getName() == "TUpButton")
					{
						 settings.waterSettings.mRestParticlesPerMetre += 1.0;
					}
					else
					{
						if(settings.waterSettings.mRestParticlesPerMetre - 1.0 > 0)
						{
							settings.waterSettings.mRestParticlesPerMetre -= 1.0;
						}
						else
						{
							settings.waterSettings.mRestParticlesPerMetre = 0;
						}
					}
					value = Ogre::StringConverter::toString(settings.waterSettings.mRestParticlesPerMetre);
					break;
				case WaterWindow::Param_PacketSizeMultiplier:
					if(button->getName() == "TUpButton")
					{
						settings.waterSettings.mPacketSizeMultiplier += 1;
					}
					else
					{
						if(int(settings.waterSettings.mPacketSizeMultiplier) - 1 > 0)
						{
							settings.waterSettings.mPacketSizeMultiplier -= 1;
						}
						else
						{
							settings.waterSettings.mPacketSizeMultiplier = 0;
						}
					}
					value = Ogre::StringConverter::toString(settings.waterSettings.mPacketSizeMultiplier);
					break;
				case WaterWindow::Param_MotionLimitMultiplier:
					if(button->getName() == "TUpButton")
					{
						settings.waterSettings.mMotionLimitMultiplier += 1.0;
					}
					else
					{
						if(settings.waterSettings.mMotionLimitMultiplier - 1.0 > 0)
						{
							settings.waterSettings.mMotionLimitMultiplier -= 1.0;
						}
						else
						{
							settings.waterSettings.mMotionLimitMultiplier = 0;
						}
					}
					value = Ogre::StringConverter::toString(settings.waterSettings.mMotionLimitMultiplier);
					break;
				case WaterWindow::Param_CollisionDistanceMultiplier:
					if(button->getName() == "TUpButton")
					{
						settings.waterSettings.mCollisionDistanceMultiplier += 0.1;
					}
					else
					{
						if(settings.waterSettings.mCollisionDistanceMultiplier - 0.1 > 0)
						{
							settings.waterSettings.mCollisionDistanceMultiplier -= 0.1;
						}
						else
						{
							settings.waterSettings.mCollisionDistanceMultiplier = 0;
						}
					}
					value = Ogre::StringConverter::toString(settings.waterSettings.mCollisionDistanceMultiplier);
					break;
				case WaterWindow::Param_Stiffness:
					if(button->getName() == "TUpButton")
					{
						settings.waterSettings.mStiffness += 1.0;
					}
					else
					{
						if(settings.waterSettings.mStiffness - 1.0 > 0)
						{
							settings.waterSettings.mStiffness -= 1.0;
						}
						else
						{
							settings.waterSettings.mStiffness = 0;
						}
					}
					value = Ogre::StringConverter::toString(settings.waterSettings.mStiffness);
					break;
				case WaterWindow::Param_Viscosity:
					if(button->getName() == "TUpButton")
					{
						settings.waterSettings.mViscosity += 1.0;
					}
					else
					{
						if(settings.waterSettings.mViscosity - 1.0 > 0)
						{
							settings.waterSettings.mViscosity -= 1.0;
						}
						else
						{
							settings.waterSettings.mViscosity = 0;
						}
					}
					value = Ogre::StringConverter::toString(settings.waterSettings.mViscosity);
					break;
				case WaterWindow::Param_RestDensity:
					if(button->getName() == "TUpButton")
					{
						settings.waterSettings.mRestDensity += 100;
					}
					else
					{
						if(settings.waterSettings.mRestDensity - 100 > 0)
						{
							settings.waterSettings.mRestDensity -= 100;
						}
						else
						{
							settings.waterSettings.mRestDensity = 0;
						}
					}
					value = Ogre::StringConverter::toString(settings.waterSettings.mRestDensity);
					break;
				case WaterWindow::Param_StartHeight:
					if(button->getName() == "TUpButton")
					{
						settings.waterSettings.mStartHeight += 0.1;
					}
					else
					{
						if(settings.waterSettings.mStartHeight - 0.1 > 0)
						{
							settings.waterSettings.mStartHeight -= 0.1;
						}
						else
						{
							settings.waterSettings.mStartHeight = 0;
						}
					}
					value = Ogre::StringConverter::toString(settings.waterSettings.mStartHeight);
					break;
				case WaterWindow::Param_ParticleLifetime:
					if(button->getName() == "TUpButton")
					{
						settings.waterSettings.mParticleLifetime += 10.0;
					}
					else
					{
						if(settings.waterSettings.mParticleLifetime - 10.0 > 0)
						{
							settings.waterSettings.mParticleLifetime -= 10.0;
						}
						else
						{
							settings.waterSettings.mParticleLifetime = 0;
						}
					}
					value = Ogre::StringConverter::toString(settings.waterSettings.mParticleLifetime);
					break;
				case WaterWindow::Param_Rate:
					if(button->getName() == "TUpButton")
					{
						settings.waterSettings.mRate += 10.0;
					}
					else
					{
						if(settings.waterSettings.mRate - 10.0 > 0)
						{
							settings.waterSettings.mRate -= 10.0;
						}
						else
						{
							settings.waterSettings.mRate = 0;
						}
					}
					value = Ogre::StringConverter::toString(settings.waterSettings.mRate);
					break;
				case WaterWindow::Param_FluidSpeed:
					if(button->getName() == "TUpButton")
					{
						settings.waterSettings.mFluidSpeed += 0.1;
					}
					else
					{
						if(settings.waterSettings.mFluidSpeed - 0.1 > 0)
						{
							settings.waterSettings.mFluidSpeed -= 0.1;
						}
						else
						{
							settings.waterSettings.mFluidSpeed = 0;
						}
					}
					value = Ogre::StringConverter::toString(settings.waterSettings.mFluidSpeed);
					break;
				case WaterWindow::Param_ReplusionCoefficient:
					if(button->getName() == "TUpButton")
					{
						settings.waterSettings.mReplusionCoefficient += 0.1;
					}
					else
					{
						if(settings.waterSettings.mReplusionCoefficient - 0.1 > 0)
						{
							settings.waterSettings.mReplusionCoefficient -= 0.1;
						}
						else
						{
							settings.waterSettings.mReplusionCoefficient = 0;
						}
					}
					value = Ogre::StringConverter::toString(settings.waterSettings.mReplusionCoefficient);
					break;
				case WaterWindow::Param_DimensionX:
					if(button->getName() == "TUpButton")
					{
						settings.waterSettings.mDimensionX += 0.1;
					}
					else
					{
						if(settings.waterSettings.mDimensionX - 0.1 > 0)
						{
							settings.waterSettings.mDimensionX -= 0.1;
						}
						else
						{
							settings.waterSettings.mDimensionX = 0;
						}
					}
					value = Ogre::StringConverter::toString(settings.waterSettings.mDimensionX);
					break;
				case WaterWindow::Param_DimensionY:
					if(button->getName() == "TUpButton")
					{
						settings.waterSettings.mDimensionY += 0.1;
					}
					else
					{
						if(settings.waterSettings.mDimensionY - 0.1 > 0)
						{
							settings.waterSettings.mDimensionY -= 0.1;
						}
						else
						{
							settings.waterSettings.mDimensionY = 0;
						}
					}
					value = Ogre::StringConverter::toString(settings.waterSettings.mDimensionY);
					break;
				case WaterWindow::Param_ParticleSize:
					if(button->getName() == "TUpButton")
					{
						settings.waterSettings.mParticleSize += 1.0;
					}
					else
					{
						if(settings.waterSettings.mParticleSize - 1.0 > 0)
						{
							settings.waterSettings.mParticleSize -= 1.0;
						}
						else
						{
							settings.waterSettings.mParticleSize = 1;
						}
					}
					value = Ogre::StringConverter::toString(settings.waterSettings.mParticleSize);
					break;
				}

				text.append(value);
				mGui->mWaterWindow->mParamValueLabel->setCaption(text);
			}
			else if(button->getName() == "TResetButton")
			{
				resetPhysics();
				mGui->resetMenus();
			}
			else if(button->getName() == "TSnowButton")
			{
				mWeatherSystem->advanceSnowLevel();
				bTerrainLoaded = false;
			}
			else if(button->getName() == "TFireButton")
			{
				mPhysXWorld->fireAllEmitters();
			}
			else if(button->getName() == "TStaticButton")
			{
				mPhysXWorld->setStaticAllEmitters();
			}
			else if(button->getName() == "TSaveButton")
			{
				mSceneExporter.exportSceneToXml("New map","This is a custom scene", mPredefinedCameraDescriptions,mMap,mWeatherSystem,mPhysXWorld);
				mTrayMgr->showOkDialog("Scene exporter","Scene saved! On the next start it will be listed in the main menu!");
			}
			else if(button->getName() == "TSaveCameraButton")
			{
				mPredefinedCameraDescriptions->saveCamera(mCamera);	
				mTrayMgr->showOkDialog("SandBox","Camera position and orientation saved!");
			}

	}
	else //we are in the mein menu
	{
		if(  (button->getName() == "TExitButton") )
		{
			this->mShutDown = true;
		}
		else if(  (button->getName() == "TStartButton") )
		{
			mGui->mMainMenu->hide();
			buildWorld(mSceneImporter.saveFiles.at(mGui->mMainMenu->getSelectionIndex())->getFileName());
		}

	}
}
//-------------------------------------------------------------------------------------
void SandBox::createFrameListener(void)
{
    BaseEngine::createFrameListener();

    mGui = new SandBoxGui(mCameraMan, mTrayMgr);
}
//-------------------------------------------------------------------------------------
void SandBox::loadResources(void)
{
    BaseEngine::loadResources();
}
//-------------------------------------------------------------------------------------

void SandBox::writeBenchMarkResults(Ogre::String fileName)
{

	extern AppSettings settings;
	logwriter *logFile = new logwriter(fileName,"BenchmarkStats",true);

	Ogre::String fpsData = this->getBenchMarkData();

	int width = mWindow->getWidth();
	int height = mWindow->getHeight();
	int depth = mWindow->getColourDepth();
	int FSAA = mWindow->getFSAA();
	bool fullScreen = mWindow->isFullScreen();
	bool physx;
	bool shadows = settings.applicationSettings.bUseShadows;

	if(settings.applicationSettings.bUseHardwarePhysX)
	{
		physx  = mWorld->hasHardware();
	}
	else
	{
		physx = false;
	}
	
	Ogre::String videoMode = Ogre::StringConverter::toString(width).append(" x ").append(Ogre::StringConverter::toString(height).append(" @ ").append(Ogre::StringConverter::toString(depth)).append(" bit color depth"));
	Ogre::String antialiaSing = Ogre::StringConverter::toString(FSAA);
	Ogre::String fScreen = Ogre::StringConverter::toString(fullScreen);
	Ogre::String physxHardware =  Ogre::StringConverter::toString(physx);
	Ogre::String dynamicShadows =  Ogre::StringConverter::toString(shadows);


	logFile->writeEntry("Video Mode",videoMode.data());
	logFile->writeEntry("Full screen",fScreen.data());
	logFile->writeEntry("Antialiasing",antialiaSing.data());
	logFile->writeEntry("Dynamic shadows enabled",dynamicShadows.data());
	logFile->writeEntry("PhysX enabled",physxHardware.data());
	logFile->writeEntry("Frame stats",fpsData.data());
	logFile->close();

}

//-------------------------------------------------------------------------------------